package com.atguigu.gmall.serviceutil.aspect;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.lang.reflect.Method;
import java.lang.reflect.Type;

/**
 * @author A
 * @version 1.0
 * @description: TODO
 * @date 2025/9/3 1:38
 */
@Slf4j
@Component
@Aspect
public class CacheAspect {
    @Autowired
    private CacheHelper cacheHelper;

    @Around(value = "@annotation(com.atguigu.gmall.serviceutil.annotation.AppCache)")
    public Object around(ProceedingJoinPoint joinPoint) {
        Object[] args = joinPoint.getArgs();
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        String methodName = method.getName();

        Object result = null;
        try {
            //前置通知,查询缓存
            log.info("method name:{}查询args:{}缓存", methodName, args);
            Object cacheData = cacheHelper.getCacheData(args, signature);
            if (cacheData != null) {
                log.info("method name:{}命中缓存,args:{}返回缓存数据", methodName, args);
                return cacheData;
            }
            log.info("method name:{}未命中缓存,args:{}查询布隆过滤器", methodName, args);
            //判断是否使用布隆过滤器-- 返回布隆过滤器名称是否为空
            String bloomFilterName =cacheHelper.checkUseBloomFilter(signature);
            if (StringUtils.isEmpty(bloomFilterName)){
                //不使用布隆过滤器,直接加分布式锁
                log.info("method name:{},args:{}未配置布隆过滤器,开始加分布式锁", methodName, args);
                //加分布式锁
                Boolean lockSuccess = cacheHelper.tryLock(args, signature);
                if (!lockSuccess) {
                    log.info("method name:{},args:{}加锁失败,等待1s后查询缓存", methodName, args);
                    Thread.sleep(1000);
                    return cacheHelper.getCacheData(args, signature);
                }
                log.info("method name:{},args:{}加锁成功,查询库", methodName, args);
                // 回源查库
                result = joinPoint.proceed(args);
                log.info("method name:{},args:{}查询库成功,更新缓存", methodName, args);
                //更新缓存
                cacheHelper.saveCacheData(args, result,signature);
                //开始解锁
                cacheHelper.unlock(args, signature);

            }else {
                //使用布隆过滤器,判断是否命中布隆过滤器
                Boolean isHit = cacheHelper.checkBloomFilter(args,signature);
                if (!isHit) {
                    log.info("method name:{},args:{}未命中布隆过滤器,拦截打回", methodName, args);
                    return null;
                }
                log.info("method name:{},args:{}命中布隆过滤器,开始加分布式锁", methodName, args);
                //加分布式锁
                Boolean lockSuccess = cacheHelper.tryLock(args, signature);
                if (!lockSuccess) {
                    log.info("method name:{},args:{}加锁失败,等待1s后查询缓存", methodName, args);
                    Thread.sleep(1000);
                    return cacheHelper.getCacheData(args, signature);
                }
                log.info("method name:{},args:{}加锁成功,查询库", methodName, args);
                // 回源查库
                result = joinPoint.proceed(args);
                log.info("method name:{},args:{}查询库成功,更新缓存", methodName, args);
                //更新缓存
                cacheHelper.saveCacheData(args, result,signature);
                //开始解锁
                cacheHelper.unlock(args, signature);
            }
            //返回通知
        } catch (Throwable e) {

            //异常通知
            throw new RuntimeException(e);
        }
        //后置通知
        return result;
    }
}
